"""
08_human_in_loop.py - Human-in-the-Loop Patterns
==================================================
Chapter 10: Adding human oversight and approval to agent workflows.

KEY CONCEPTS:
  ★ interrupt_before - Pause graph before a specific node
  ★ update_state() - Human provides input while paused
  ★ Resume execution - Continue from where paused

Run: python src/08_human_in_loop.py
"""
from typing import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver

class ApprovalState(TypedDict):
    request: str
    analysis: str
    approved: bool
    final_action: str

def analyze_request(state: ApprovalState) -> dict:
    return {"analysis": f"Analyzed '{state['request']}'. Recommendation: APPROVE"}

def execute_action(state: ApprovalState) -> dict:
    if state.get("approved"):
        return {"final_action": f"Action executed for: {state['request']}"}
    return {"final_action": "Action REJECTED by human reviewer."}

graph = StateGraph(ApprovalState)
graph.add_node("analyze", analyze_request)
graph.add_node("execute", execute_action)
graph.add_edge(START, "analyze")
graph.add_edge("analyze", "execute")
graph.add_edge("execute", END)

checkpointer = MemorySaver()
app = graph.compile(checkpointer=checkpointer, interrupt_before=["execute"])

if __name__ == "__main__":
    print("=" * 60)
    print("08: Human-in-the-Loop")
    print("=" * 60)
    config = {"configurable": {"thread_id": "approval_1"}}
    result = app.invoke({"request": "Deploy v2.0 to production"}, config=config)
    print(f"\n  Analysis: {result['analysis']}")
    print(f"  ⏸️  Graph paused. Waiting for human approval...")
    
    # Human approves
    app.update_state(config, {"approved": True})
    print(f"  ✅ Human approved! Resuming...")
    
    result = app.invoke(None, config=config)
    print(f"  Result: {result['final_action']}")
    print(f"\n{'=' * 60}\n✅ Human-in-the-loop complete!")
